#include "sessionfriendarea.h"
#include <QScrollBar>
#include <QVBoxLayout>
#include <QPushButton>
#include <QLabel>
#include <QStyleOption>
#include <QPainter>
#include <QTimer>

#include "model/data.h"
#include "debug.h"
#include "mainwidget.h"
#include "model/datacenter.h"

using namespace model;

SessionFriendArea::SessionFriendArea(QWidget *parent)
    : QScrollArea{parent}
{
    // 1. 设置必要的属性
    // 设置了这个属性，才能够开启滚动效果
    this->setWidgetResizable(true);
    // 设置滚动条相关的样式
    this->verticalScrollBar()->setStyleSheet("QScrollBar:vertical { width: 2px; "
                                             "background-color: rgb(241, 241, 241); }");
    this->horizontalScrollBar()->setStyleSheet("QScrollBar:horizontal { height: 0px; }");
    this->setStyleSheet("QWidget { border: none;}");

    // 2. 把 widget 创建出来
    container = new QWidget();
    container->setFixedWidth(226);
    this->setWidget(container);

    // 3. 给这个 widget 指定布局管理器，以便后续添加元素进去
    QVBoxLayout* layout = new QVBoxLayout();
    layout->setContentsMargins(0, 0, 0, 0);
    layout->setSpacing(0);
    layout->setAlignment(Qt::AlignTop);
    container->setLayout(layout);

    // for (int i = 0; i < 50; i++)
    // {
    //     QPushButton* btn = new QPushButton();
    //     btn->setText("aa");
    //     layout->addWidget(btn);
    // }

    //
#if TEST_UI
    int i = 0;
    this->addItem(SessionItemType, QString::number(i++), QIcon(":/resource/image/kindergarden.jpg"),
                  "春日部防卫队", "春日部防卫队 fire!");
    this->addItem(SessionItemType, QString::number(i++), QIcon(":/resource/image/Shin_Crayon.jpg"),
                  "野原新之助", "ENTP");
    this->addItem(SessionItemType, QString::number(i++), QIcon(":/resource/image/Mitsy.jpg"),
                  "野原美伢", "ENFP");
    this->addItem(SessionItemType, QString::number(i++), QIcon(":/resource/image/Harry.jpg"),
                  "野原广志", "ESFJ");
    this->addItem(SessionItemType, QString::number(i++), QIcon(":/resource/image/Daisy.jpg"),
                  "野原葵", "ENFP");
    this->addItem(SessionItemType, QString::number(i++), QIcon(":/resource/image/George.jpg"),
                  "风间彻", "ESTJ");
    this->addItem(SessionItemType, QString::number(i++), QIcon(":/resource/image/Nene.jpg"),
                  "樱田妮妮", "ENTJ");
    this->addItem(SessionItemType, QString::number(i++), QIcon(":/resource/image/Boo.jpg"),
                  "佐藤正男", "INTP");
    this->addItem(SessionItemType, QString::number(i++), QIcon(":/resource/image/Sally.jpg"),
                  "酢乙女爱", "ENTJ");

#endif
}

void SessionFriendArea::clear()
{
    QLayout* layout = container->layout();
    // 遍历布局管理器中的所有元素，并依次从布局管理器中删除掉
    for (int i = layout->count() - 1; i >= 0; --i)
    {
        // takeAt 能移除对应下标的元素
        QLayoutItem* item = layout->takeAt(i);
        // "释放" 对象
        if (item->widget())
        {
            // 把这个移除的内容的 widget 进行释放
            // 正常使用的时候，new 出来的对象添加到布局管理器的.....
            delete item->widget();
        }
    }
}


// 此时这个函数添加的就不是 SessionFriendItem 了，而是 SessionFriendItem 的子类
// SessionItem FriendItem ApplyItem 其中一个
void SessionFriendArea::addItem(ItemType itemType, const QString& id, const QIcon &avatar,
                                const QString &name, const QString &text)
{
    SessionFriendItem* item = nullptr;
    if (itemType == SessionItemType)
        item = new SessionItem(this, id, avatar, name, text);
    else if (itemType == FriendItemType)
        item = new FriendItem(this, id, avatar, name, text);
    else if (itemType == ApplyItemType)
        item = new ApplyItem(this, id, avatar, name);
    else
    {
        LOG("错误的 ItemType! itemType = ") << itemType;
        return;
    }
    container->layout()->addWidget(item);
}

void SessionFriendArea::clickItem(int index)
{
    if (index < 0 || index >= container->layout()->count())
    {
        LOG("点击元素的下标超出范围! index = ") << index;
        return;
    }
    QLayoutItem* layoutItem = container->layout()->itemAt(index);
    if (layoutItem == nullptr || layoutItem->widget() == nullptr)
    {
        LOG("指定的元素不存在! index = ") << index;
        return;
    }
    SessionFriendItem* item = dynamic_cast<SessionFriendItem*>(layoutItem->widget());
    item->select();
}

void SessionFriendArea::scrollToBegin()
{
    // 获取滚动条的最小值
    // "延时"
    QTimer* timer = new QTimer();
    connect(timer, &QTimer::timeout, this, [=](){
        // 获取最大值
        int minValue = this->verticalScrollBar()->minimum();
        // 设置滚动条的滚动位置
        this->verticalScrollBar()->setValue(minValue);

        timer->stop();
        timer->deleteLater();
    });
    timer->start(100);

}

////////////////////////////////////////////
/// 滚动区域中的 Item 的实现
////////////////////////////////////////////

SessionFriendItem::SessionFriendItem(QWidget *owner, const QIcon &avatar, const QString &name, const QString &text)
    : owner(owner)
{
    this->setFixedHeight(64);
    this->setStyleSheet("QWidget { background-color: rgb(233, 233, 233); }");

    // 创建网格布局管理器
    QGridLayout* layout = new QGridLayout();
    layout->setContentsMargins(10, 0, 0, 0);
    layout->setHorizontalSpacing(10);
    layout->setVerticalSpacing(0);
    this->setLayout(layout);

    // 创建头像
    QPushButton* avatarBtn = new QPushButton();
    avatarBtn->setFixedSize(40, 40);
    avatarBtn->setIconSize(QSize(40, 40));
    avatarBtn->setIcon(avatar);
    avatarBtn->setStyleSheet("QPushButton { border: none; }");
    avatarBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

    // 创建名字
    QLabel* nameLabel = new QLabel();
    nameLabel->setText(name);
    nameLabel->setFixedHeight(40);
    nameLabel->setStyleSheet("QLabel { margin-top: 5px; font-size: 13.5px; font-weight: 400; }");
    nameLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

    // 创建消息预览的 label
    messageLabel = new QLabel();
    messageLabel->setText(text);
    messageLabel->setFixedHeight(35);
    messageLabel->setStyleSheet("QLabel { margin-bottom: 5px; color: rgb(153, 153, 153); }");
    messageLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

    // 头像处于 0, 0 位置, 占据 2 行, 占据 2 列
    layout->addWidget(avatarBtn, 0, 0, 2, 2);
    // 名字处于 0, 2 位置, 占据 1 行, 占据 1 列
    layout->addWidget(nameLabel, 0, 2, 1, 8);
    // 消息预览处于 1, 2 位置, 占据 1 行, 占据 1 列
    layout->addWidget(messageLabel, 1, 2, 1, 8);
}

void SessionFriendItem::paintEvent(QPaintEvent *event)
{
    (void) event;
    QStyleOption opt;
    opt.initFrom(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}

void SessionFriendItem::mousePressEvent(QMouseEvent *event)
{
    (void)event;
    select();
}

void SessionFriendItem::enterEvent(QEnterEvent *event)
{
    (void)event;

    // 当前这个 item 是选中状态，则背景色不受到该逻辑影响
    if (this->selected)
        return;
    // 设置一个更深的颜色
    this->setStyleSheet("QWidget { background-color: rgb(215, 215, 215); }");
}

void SessionFriendItem::leaveEvent(QEvent *event)
{
    (void)event;

    // 当前这个 item 是选中状态，则背景色不受到该逻辑影响
    if (this->selected)
        return;
    // 还原背景色
    this->setStyleSheet("QWidget { background-color: rgb(233, 233, 233); }");
}

void SessionFriendItem::select()
{
    // 鼠标点击时会触发这个函数
    // 还原其他元素的背景色
    // 拿到所有的兄弟元素
    const QObjectList children = this->parentWidget()->children();
    for (QObject* child : children)
    {
        if (!child->isWidgetType())  // 判断是否是 widget
            continue;

        // 如果是 widget ，把 child 强转成 SessionFriendItem
        SessionFriendItem* item = dynamic_cast<SessionFriendItem*>(child);
        if (item->selected)
        {
            item->selected = false;
            item->setStyleSheet("QWidget { background-color: rgb(233, 233, 233); }");
        }
    }

    // 点击时修改背景色
    this->setStyleSheet("QWidget { background-color: rgb(200, 200, 200); }");
    this->selected = true;

    // 调用 active
    this->active();
}

void SessionFriendItem::active()
{
    // 父类的 active
    // 并不需要实现任何逻辑
}

////////////////////////////////////////////
/// 会话 Item 的实现
////////////////////////////////////////////

SessionItem::SessionItem(QWidget *owner, const QString &chatSessionId, const QIcon &avatar,
                         const QString &name, const QString &lastMessage)
    : SessionFriendItem(owner, avatar, name, lastMessage)
    , chatSessionId(chatSessionId)
    , text(lastMessage)
{
    // 处理更新最后一个消息的信号
    DataCenter* dataCenter = DataCenter::getInstance();
    connect(dataCenter, &DataCenter::updateLastMessage, this, &SessionItem::updateLastMessage);

    // 需要显示未读消息的数目 客户端重启后未读消息仍然能正确显示
    int unread = dataCenter->getUnread(chatSessionId);
    if (unread > 0)
        this->messageLabel->setText(QString("[%1条] ").arg(unread) + text);
}

void SessionItem::active()
{
    // 加载会话的历史列表
    LOG("点击 SessionItem 触发的逻辑! chatSessionId = ") << chatSessionId;

    // 设计到内存数据操作 网络通信 界面变更
    MainWidget* mainWidget = MainWidget::getInstance();
    mainWidget->loadRecentMessage(chatSessionId);

    // 清空未读消息的数据 并更新显示
    DataCenter* dataCenter = DataCenter::getInstance();
    dataCenter->clearUnread(chatSessionId);

    // 更新界面显示 前面未读消息删除
    this->messageLabel->setText(text);

}

void SessionItem::updateLastMessage(const QString &chatSessionId)
{
    DataCenter* dataCenter = DataCenter::getInstance();
    // 1. 判定 chatSession 是否匹配
    if (this->chatSessionId != chatSessionId)
        return;         // 当前 SessionItem 不是正在发信息的 SessionItem

    // 2. ChatSessionId 匹配 获取最后一条消息
    QList<Message>* messageList = dataCenter->getRecentMessageList(chatSessionId);
    if (messageList == nullptr || messageList->size() == 0)
        return;

    const Message& lastMessage = messageList->back();

    // 3. 明确显示的文本内容
    if (lastMessage.messageType == TEXT_TYPE)
        text = lastMessage.content;
    else if (lastMessage.messageType == IMAGE_TYPE)
        text = "[图片]";
    else if (lastMessage.messageType == FILE_TYPE)
        text = "[文件]";
    else if (lastMessage.messageType == SPEECH_TYPE)
        text = "[语音]";
    else
    {
        LOG("错误的消息类型!");
        return;
    }

    // 4. 显示到 Item 上
    // 判定当前会话是否是选中的会话 如果是 不会更新任何未读消息
    // 如果不是 unread > 0 则更新
    if (chatSessionId == dataCenter->getCurrentChatSessionId())
        this->messageLabel->setText(text);
    else
    {
        int unread = dataCenter->getUnread(chatSessionId);
        if (unread > 0)
            this->messageLabel->setText(QString("[%1条] ").arg(unread) + text);
    }

}

////////////////////////////////////////////
/// 好友 Item 的实现
////////////////////////////////////////////

FriendItem::FriendItem(QWidget *owner, const QString &userId, const QIcon &avatar,
                       const QString &name, const QString &description)
    : SessionFriendItem(owner, avatar, name, description)
    , userId(userId)
{

}

void FriendItem::active()
{
    // 激活会话列表
    LOG("点击 FriendItem 触发的逻辑! userId = ") << userId;

    MainWidget* mainWidget = MainWidget::getInstance();
    mainWidget->switchSession(userId);
}

////////////////////////////////////////////
/// 好友申请 Item 的实现
////////////////////////////////////////////

ApplyItem::ApplyItem(QWidget *owner, const QString &userId, const QIcon &avatar, const QString &name)
    : SessionFriendItem(owner, avatar, name, "")
    , userId(userId)
{
    // 1. 移除父类的 messageLabel
    QGridLayout* layout = dynamic_cast<QGridLayout*>(this->layout());
    layout->removeWidget(messageLabel);
    // 要记得释放内存，否则会内存泄露
    delete messageLabel;

    // 2. 创建两个按钮出来
    QPushButton* acceptBtn = new QPushButton();
    acceptBtn->setText("接受");
    acceptBtn->setStyleSheet("QPushButton {"
                             "background-color: rgb(26, 173, 25);" // 设置背景颜色为绿色
                             "color: white;" // 设置字体颜色为白色
                             "}");
    acceptBtn->setFixedSize(45, 25);

    QPushButton* rejectBtn = new QPushButton();
    rejectBtn->setStyleSheet("QPushButton {"
                             "background-color: rgb(26, 173, 25);" // 设置背景颜色为绿色
                             "color: white;" // 设置字体颜色为白色
                             "}");
    rejectBtn->setFixedSize(45, 25);
    rejectBtn->setText("拒绝");

    // 3. 添加到布局管理器中
    layout->addWidget(acceptBtn, 1, 2, 1, 1);
    layout->addWidget(rejectBtn, 1, 5, 1, 1);

    // 4. 添加信号槽
    connect(acceptBtn, &QPushButton::clicked, this, &ApplyItem::acceptFriendApply);
    connect(rejectBtn, &QPushButton::clicked, this, &ApplyItem::rejectFriendApply);
}

void ApplyItem::acceptFriendApply()
{
    // 发送网络请求 告知同意好友申请
    DataCenter* dataCenter = DataCenter::getInstance();
    // 同意谁的好友申请了
    dataCenter->acceptFriendApplyAsync(this->userId);
}

void ApplyItem::rejectFriendApply()
{
    // 发送网络请求 告知拒绝好友申请
    DataCenter* dataCenter = DataCenter::getInstance();
    // 拒绝谁的好友申请了
    dataCenter->rejectFriendApplyAsync(this->userId);
}

void ApplyItem::active()
{
    // 这个函数不需要任何事发生
    LOG("点击 ApplyItem 触发的逻辑! userId = ") << userId;
}
